<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h3>IIFE(Immediately-invoked function expression)</h3>
		<ul>
			<li>IIFE一般是匿名函数，在定义完后立即执行</li>
			<li>IIFE表面上看可以减少定义函数对global空间的名称污染</li>
			<button onclick="funcTest1()">运行例子</button>
		</ul>
		<script>
			function funcTest1(){
				// 最简单的IIFE调用
		        var result1 = (function () {
		            return "Hello IIFE!";
		        })();
			    console.log(result1);//Hello IIFE!
			
		        // 也可以定义带参数的IIFE
		        var result2 = (function (num) {
		            var total = 0;
		            for (var i = 1; i <= num; i++) {
		                total += i;
		            }
		            return total;
		        })(10);
		        console.log(result2);//55
	        }
		</script>
		
		<h3>使用IIFE定义类型</h3>
		<ul>
			<li>IIFE可以用于对外隐藏部分内部实现，减少对global空间的污染</li>
			<button onclick="funcTest2()">运行例子</button>
		</ul>
		<script>
			(function(){
				var _name = "";							// 局部变量无法在IIFE外部访问
				var _gender = "";
				
				// 请注意，下面的Person作为类型定义，而不是对象实例
				Person = function(name, gender){		// 因为没有使用var, Person类型被定义在global空间中
					_name = name;
					_gender = gender;
				};
				Person.prototype.getName = function(){
					return _name;
				};
				Person.prototype.setName = function (newName){
					_name = newName;
				};
				Person.prototype.getGender = function(){
					return _gender;
				}
				Person.prototype.setGender = function(newGender){
					_gender = newGender
				}
				Person.prototype.toString = function(){
					return "name:" + _name + ",gender:" + _gender;
				}
			})();
			function funcTest2(){
				var p = new Person('jerry', '男');  // window.Person
				console.log(p.toString());
			}
		</script>
		
		<h3>返回singleton对象(Literal形式)</h3>
		<ul>
			<li>通过某函数返回一个对象实例(而不是类型定义)，可以作为Singleton模式</li>
			<button onclick="funcTest3()">运行例子</button>
		</ul>
		<script>
			var sortedArray = (function(){			// sortedArray代表一个对象实例，而不是一个类型定义
				var array = new Array();
				return {
					count : function(){
						return array.length;
					},
					add : function(value){
						var length = array.length;
						if(length == 0){			// 集合为空，直接放在第一个元素
							array[0] = value;
							return;
						}
						
						var i = 0;
						var insertedIndex = 0;
						while(value > array[i] && i<length){
							i++;
						}
						insertedIndex = i;			// insertedIndex是新元素插入在集合中的下标位置
						
						// 将后续元素依次向后挪动一个位置
						for(var i=length;i>insertedIndex;i--){
							array[i] = array[i-1];
						}
						
						array[insertedIndex] = value;	// 最后在指定位置填入新元素
					},
					remove : function(value){
						var length = array.length;
						var index = -1;
						var i = 0;
						var indexStart=0,indexEnd=0;
						
						while(i < length && value > array[i]){
							i++;
						}
						indexStart = i;				// 找到value第一次出现的下标位置
						while(i < length && value == array[i]){
							i++;
						}
						indexEnd = i;					// 找到最近一个大于value的元素下表位置
						
						array.splice(indexStart, indexEnd-indexStart);	// 删除元素
					},
					clear: function(){
						array.length = 0;
					},
					items : function(index){
						return array[index];
					}
				};
			})();
			
			function funcTest3(){
				//console.log(sortedArray.array.length);	// 不能直接访问内部的array变量
				sortedArray.clear();
				
				sortedArray.add(5);
				sortedArray.add(7);
				sortedArray.add(3);
				sortedArray.add(3);
				sortedArray.add(8);
				sortedArray.add(1);
				var length = sortedArray.count();
				console.log("集合中现有" + length + "个元素");
				for(var i=0;i<length;i++){
					console.log(sortedArray.items(i));
				}
				
				sortedArray.remove(3);
				sortedArray.remove(1);
				sortedArray.remove(8);
				length = sortedArray.count();
				console.log("集合中现有" + length + "个元素");
				for(var i=0;i<length;i++){
					console.log(sortedArray.items(i));
				}
			}
		</script>
	</body>
</html>
